#include "StdAfx.h"
#include "DXCommon.h"
#include "../sgp/Image.h"
#include "../sgp/VideoSurfaceLock.h"
#include "../sgp/VideoSurfaceHandle.h"

namespace ja2{ namespace sgp
{
	VideoSurfaceHandle::VideoSurfaceHandle(IDirectDrawSurfacePtr pSurfaceData, IDirectDrawSurfacePtr pSavedSurfaceData, COLORVAL TransparentColor, std::uint_least16_t Width, std::uint_least16_t Height)
		:  m_pSurfaceData(pSurfaceData), m_pSavedSurfaceData(pSavedSurfaceData), TransparentColor(TransparentColor), m_Width(Width), m_Height(Height)
	{
		// Get surface and find out if it is in memory
		DDSURFACEDESC2 surface_description = DDSURFACEDESC2();
		surface_description.dwSize = sizeof(DDSURFACEDESC);
		surface_description.dwFlags = DDSD_CAPS;
		m_pSurfaceData->GetSurfaceDesc(&surface_description);
		
		m_IsInVideo = (surface_description.ddsCaps.dwCaps == DDSCAPS_VIDEOMEMORY);
	}

	uint_least16_t VideoSurfaceHandle::height() const
	{
		return m_Height;
	}

	uint_least16_t VideoSurfaceHandle::width() const
	{
		return m_Width;
	}

	bool VideoSurfaceHandle::is_in_video() const
	{
		return m_IsInVideo;
	}
	
	void VideoSurfaceHandle::update_backup()
	{
		RECT dest_rect = {0, 0, m_Width, m_Height};
		// Copy all contents into backup buffer
		dx_attempt(m_pSurfaceData->BltFast(0, 0, m_pSavedSurfaceData, &dest_rect, DDBLTFAST_NOCOLORKEY));
	}

	void VideoSurfaceHandle::fill(COLORVAL Color)
	{
		// Fill whole surface
		fill(Color, Rect());
	}

	void VideoSurfaceHandle::fill(COLORVAL Color, Rect const &Rect)
	{
		RECT fill_rect = static_cast<RECT>(Rect);
		// Set blitter params
		DDBLTFX	blitter_fx;
		blitter_fx.dwSize = sizeof( blitter_fx );
		blitter_fx.dwFillColor = Color;
		// Blit
		dx_attempt(m_pSurfaceData->Blt((Rect.empty() ? NULL : &fill_rect), NULL, NULL, DDBLT_COLORFILL, &blitter_fx));
		// Update backup if needed
		try_update_backup();
	}

	void VideoSurfaceHandle::try_update_backup()
	{
//x		if(get_memory_usage == MU_VIDEO && !(get_memory_usage(VSURFACE_RESERVED_SURFACE) )
		if(m_IsInVideo)
			update_backup();
	}

	void VideoSurfaceHandle::blit_fast(VideoSurfaceHandle &SrcSurface, std::uint_least16_t DestX, std::uint_least16_t DestY, Rect const &SrcRect)
	{
		blit_fast_generic(SrcSurface, DestX, DestY, SrcRect, DDBLTFAST_NOCOLORKEY);
	}

	void VideoSurfaceHandle::blit_fast_src_color_key(VideoSurfaceHandle &SrcSurface, std::uint_least16_t DestX, std::uint_least16_t DestY, Rect const &SrcRect)
	{
		blit_fast_generic(SrcSurface, DestX, DestY, SrcRect, DDBLTFAST_SRCCOLORKEY);
	}

	void VideoSurfaceHandle::blit_fast_dest_color_key(VideoSurfaceHandle &SrcSurface, std::uint_least16_t DestX, std::uint_least16_t DestY, Rect const &SrcRect)
	{
		blit_fast_generic(SrcSurface, DestX, DestY, SrcRect, DDBLTFAST_DESTCOLORKEY);
	}

	void VideoSurfaceHandle::blit(VideoSurfaceHandle &SrcSurface, Rect const &SrcRect, Rect const &DestRect, std::uint_least32_t Flags)
	{
		blit_generic(SrcSurface, SrcRect, DestRect, Flags, NULL);
	}

	void VideoSurfaceHandle::blit_mirror_y(VideoSurfaceHandle &SrcSurface, Rect const &SrcRect, Rect const &DestRect, std::uint_least32_t Flags)
	{
		// Set mirroring
		DDBLTFX fx = DDBLTFX();
		fx.dwSize = sizeof(fx);
		fx.dwDDFX = DDBLTFX_MIRRORUPDOWN;
		// blit
		blit_generic(SrcSurface, SrcRect, DestRect, Flags, &fx);
	}

	void VideoSurfaceHandle::blit_generic(VideoSurfaceHandle &SrcSurface, Rect const &SrcRect, Rect const &DestRect, std::uint_least32_t Flags, LPDDBLTFX pFx)
	{
		RECT dest_rect = DestRect;
		RECT src_rect = SrcRect;

		dx_attempt(m_pSurfaceData->Blt(&dest_rect, SrcSurface.m_pSurfaceData, &src_rect, Flags | DDBLT_ASYNC, pFx));
	}

	void VideoSurfaceHandle::blit_fast_generic(VideoSurfaceHandle &SrcSurface, std::uint_least16_t DestX, std::uint_least16_t DestY, Rect const &SrcRect, std::uint_least32_t Flags)
	{
		RECT src_rect = SrcRect;

		dx_attempt(m_pSurfaceData->BltFast(DestX, DestY, SrcSurface.m_pSurfaceData, &src_rect, Flags | DDBLTFAST_WAIT));
	}

	void VideoSurfaceHandle::flip()
	{
		dx_attempt(m_pSurfaceData->Flip(NULL, DDFLIP_WAIT ));
	}
} /*sgp*/} /*ja2*/